﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;

namespace NetTookKits.IOCP
{
    public class AsyncSocketClient
    {
        #region data members
        //接收缓存
        protected Byte[] m_asyncReceiveBuffer;
        //接收事件参数
        protected SocketAsyncEventArgs m_receiveEventArgs;
        //发送缓存
        protected Byte[] m_sendBuffer;
        //发送事件参数
        protected SocketAsyncEventArgs m_sendEventArgs;
        //连接socket
        protected Socket m_connectSocket;
        #endregion
        #region properties
        //接收缓存
        public byte[] ReceiveBuffer { 
            get{ 
                return m_asyncReceiveBuffer; 
            } 
            set { 
                m_asyncReceiveBuffer = value; 
            }
        }
        //接收事件参数
        public SocketAsyncEventArgs ReceiveEventArgs { 
            get {
                return m_receiveEventArgs;
            } set { 
                m_receiveEventArgs = value;
            } 
        }
        //发送缓存
        public byte[] SendBuffer { 
            get { 
                return m_sendBuffer; 
            } set { 
                m_sendBuffer = value; 
            } 
        }
        //发送事件参数
        public SocketAsyncEventArgs SendEventArgs { 
            get { 
                return m_sendEventArgs; 
            } set { 
                m_sendEventArgs = value; 
            } 
        }
        //连接socket
        public Socket ConnectSocket
        {
            get { return m_connectSocket; }
            set
            {
                m_connectSocket = value;
                Array.Clear(m_asyncReceiveBuffer, 0, m_asyncReceiveBuffer.Length);
                Array.Clear(m_sendBuffer, 0, m_sendBuffer.Length);
                m_receiveEventArgs.AcceptSocket = m_connectSocket;
                m_sendEventArgs.AcceptSocket = m_connectSocket;
            }
        }
        #endregion
        #region constructors
        public AsyncSocketClient(int receiveBufferSize, int sendBufferSize)
        {
            m_connectSocket = null;
            m_receiveEventArgs = new SocketAsyncEventArgs();
            m_receiveEventArgs.UserToken = this;
            m_asyncReceiveBuffer = new byte[receiveBufferSize];
            m_sendBuffer = new byte[sendBufferSize];
            m_sendEventArgs = new SocketAsyncEventArgs();
            m_sendEventArgs.UserToken = this;
            m_receiveEventArgs.SetBuffer(m_asyncReceiveBuffer, 0, m_asyncReceiveBuffer.Length);
            m_sendEventArgs.SetBuffer(m_sendBuffer, 0, m_sendBuffer.Length);
        }
        #endregion
        #region methods
        public void ClearRecvBuffer()
        {
            Array.Clear(m_asyncReceiveBuffer, 0, m_asyncReceiveBuffer.Length);
        }
        private bool ProcessSend(SocketAsyncEventArgs e)
        {
            bool ret = false;
            try
            {
                AsyncSocketClient userToken = e.UserToken as AsyncSocketClient;
                if (e.SocketError == SocketError.Success)
                {
                    ret = true;
                }
                else
                {
                    ret = false;
                }
            }
            catch (Exception exp)
            {
                ret = false;
                throw exp;
            }
            return ret;
        }
        public bool SendAsync(byte[] buffer, int offset, int count)
        {
            if (this.ConnectSocket == null) return false;
            this.SendEventArgs.SetBuffer(buffer, offset, count);
            bool delayToEvent = this.ConnectSocket.SendAsync(this.SendEventArgs);
            if (!delayToEvent)
            {
                return ProcessSend(this.SendEventArgs);
            }
            else
            {
                return true;
            }
        }
        #endregion
    }
}
